﻿// =====================================================
// Copyright (C) 2016-2020 Fanjia
// All rights reserved
// 机器名称: PC-LIWEI
// 创建时间: 2020/2/14 14:57:30
// 创 建 人: 李伟
// ======================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;

namespace WindowsFormsApplication1.Common
{
    public class RasBouncyCastle
    {
        private static string publicKeyFile = Path.Combine(AppContext.BaseDirectory, "RSA", "fanjia_public.key");
        private static string privateKeyFile = Path.Combine(AppContext.BaseDirectory, "RSA", "private.key");

        static string PublicKey = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcCkVqrvOWXdySj3xpEzu6X6baKHmw/Lej4pKtix479V9wtMYI6YFB/HMmJCvnWp/NKWOu/q3K3/GDiOWW1LZLYWsIyb3egnTj3V855qwek6twY0eaerSsdQCpTP0ElPFwFWr0lwKxQOqVvqbeWrbTyFyD3QM1r5rTClfHr2pkcrPmCI8UWiR+nJFmfaXJC3GxI7djEy0RkZBYap+5piQx/hNXJ8U4eYIMD8AJVy/v63wysJBSwLbhSbnSdYMpR2HJIJYycPEdSzBf6jRhManJeWDyfC2jLzYJbexsftvBrx12Hysvt3q3UCOb9I5KYqvyvHXAFWEE8ovZ0Un31LmwIDAQAB";
        static string PriKey = @"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNwKRWqu85Zd3JKPfGkTO7pfptooebD8t6Pikq2LHjv1X3C0xgjpgUH8cyYkK+dan80pY67+rcrf8YOI5ZbUtkthawjJvd6CdOPdXznmrB6Tq3BjR5p6tKx1AKlM/QSU8XAVavSXArFA6pW+pt5attPIXIPdAzWvmtMKV8evamRys+YIjxRaJH6ckWZ9pckLcbEjt2MTLRGRkFhqn7mmJDH+E1cnxTh5ggwPwAlXL+/rfDKwkFLAtuFJudJ1gylHYckgljJw8R1LMF/qNGExqcl5YPJ8LaMvNglt7Gx+28GvHXYfKy+3erdQI5v0jkpiq/K8dcAVYQTyi9nRSffUubAgMBAAECggEBALt0oQVpNQ0JVxiYH66kygpTvSa35m6K5GraSW2FAgWqZCrw+0QZhksHbNflmEOoNhhm0IKf5U3rpLcvh9nH7uGx2Fg/sx5pDa6GPfB4S3GiCWGI4LRZ44D8uFr7m557u/gMuyp2cSB+ZKE+YgaAMkAS3RxD3PV9FG8LHCqeaSuxlpkGHOxMRwqj6iBVj2IcSkCWVTOJVMPbNFdR9IrJoSoIk977sT9nwRGa17Ipa7tN+9aWabasbAzePqwxWOmhtK8sjS7Q4ZrHbZnACEVpam0TuX3BO4Wszh6oDlA7ty6A4JXV0Lf424vaOjJO2o/4aQs0UXSGyzY52JWOEJKA1ekCgYEA9GXYXk0W2thfMSg3LBOxzPvEowZUK7brZBUrW17RUCGRrDMmmJelQnHszdEZcxyFndkyNb6a4iQ5TO+Yhr6K4e1AO4J7I/dvnFsFUCWs5aoF14BGvDgAlfYEXNCcJD4+DxduV1SWrCcKHnq0+Z40NHLKq883rFVymKXQEYLQfG0CgYEA14UkW+cKYIYt6q6AU20bAYuSZJkL5IcB3d1f83QcC9fCxZEfSUCDLlkk8ShiQytBAOPPUBQ4A2c7q4RKfiTKJP6NjpjwEe6K5v6s4RLrukXIs/C4VRpj19R0ZZ7IrSV0hAUEPoHs/P3Tl+/22o3ZQWutHf+umyByy9qq3KsPUycCgYAectXbIdWYHF73u9/r0ORU+oUMHoy8CYUYKf8F2jFPv27ruk+zsSj4t0LefY+jJMmM2fOEeKPJSuQMrskc+H5LGYjoISCAYaJ5I2ntC1SYJG+n4qZtari/9i+i9KaPaWXH8Y5guPwwpIiBNZ54fvpYEnknoKB6CwdE91uN4vNgnQKBgDze3+wND0M/4owcCSaG9E+1af17tH4xG3fcZJNQQfOeVuaSHHIGBIb8qpBqRYaPGubzcMQ/Uaq0Z4gD7z49idJ1Cuoxi+ykoRqo548SVv3fY9ZesNFoiLaWzOE+vZMZtxTqjc5Rx+uUjUSmg+QqmCgAD38fjeNGgOXOtt9oeQWVAoGBAODVpMrxiPWyQglaAHwGo1HjOBxtRA0pZxdud8pRSl1TckCOpHm3iWJNLbOU3unjeKX8qE4PX0e5AZ65zfoqGOaPBLbALUnwZ+BxENlm6HH5Cm4eXf2oOaSEgLa5fNiEJzFoYirO2MKkJLwDUOSB8cw8DrzO3qTe1FGQwu+tQvL7";

        /// <summary>
        /// 私钥加密2
        /// </summary>
        /// <param name="content">加密内容</param>
        /// <param name="PrivateKey">PKCS8私钥</param>
        /// <returns></returns>
        public static string EncryptByPrivateKey2(string content, string PrivateKey)
        {
            RsaKeyParameters PrivateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(PrivateKey));
            var original = new BigInteger(Encoding.UTF8.GetBytes(content));

            //加密
            var encrypted = original.ModPow(PrivateKeyParam.Exponent, PrivateKeyParam.Modulus);
            //16进制
            return PayUtils.byteArray2HexString(encrypted.ToByteArray());
            //base64
            //return Convert.ToBase64String(encrypted.ToByteArray());
        }
        /// <summary>
        /// 公钥解密2
        /// </summary>
        /// <param name="content">解密内容</param>
        /// <param name="PublicKey">PKCS8公钥</param>
        /// <returns></returns>
        public static string DecryptByPublicKey2(string content, string PublicKey)
        {
            //base64
            //byte[] byteData = Convert.FromBase64String(content);
            //16进制
            var data = PayUtils.hexString2ByteArray(content);
            RsaKeyParameters PublicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(PublicKey));
            var encrypted = new BigInteger(data);

            //解密
            var decrypted = encrypted.ModPow(PublicKeyParam.Exponent, PublicKeyParam.Modulus);
            return Encoding.UTF8.GetString(decrypted.ToByteArray());

        }

        /// <summary>
        /// RSA公钥加密
        /// </summary>
        /// <param name="content">加密内容</param>
        /// <param name="publickey">公钥</param>
        /// <returns></returns>
        public static string EncryptByPublicKey(string content, string publicKey)
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
            var original = new BigInteger(Encoding.UTF8.GetBytes(content));

            //加密
            var encrypted = original.ModPow(publicKeyParam.Exponent, publicKeyParam.Modulus);
            //16进制
            //return PayUtils.byteArray2HexString(encrypted.ToByteArray());
            //base64
            return Convert.ToBase64String(encrypted.ToByteArray());
        }
        /// <summary>
        /// RSA私钥解密
        /// </summary>
        /// <param name="content">解密内容</param>
        /// <param name="privateKey">私钥</param>
        /// <returns></returns>
        public static string DecryptByPrivateKey(string content, string privateKey)
        {
            //base64
            byte[] byteData = Convert.FromBase64String(content);
            //16进制
            //var data = PayUtils.hexString2ByteArray(content);
            RsaKeyParameters privateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
            var encrypted = new BigInteger(byteData);

            //解密
            var decrypted = encrypted.ModPow(privateKeyParam.Exponent, privateKeyParam.Modulus);
            return Encoding.UTF8.GetString(decrypted.ToByteArray());

        }

        #region MyRegion

        public static string GetNonce(string randomStr)
        {
            var maxBlock = 245;
            int offset = 0;
            int i = 0;
            var outBytes = new List<byte>();

            var pubKey = new PemReader(new StreamReader(publicKeyFile)).ReadObject() as AsymmetricKeyParameter;
            IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
            c.Init(true, pubKey);
            var data = Encoding.UTF8.GetBytes(randomStr);
            var inputLength = data.Length;
            while (inputLength - offset > 0)
            {
                if (inputLength - offset > maxBlock)
                {
                    outBytes.AddRange(c.DoFinal(data, offset, maxBlock));
                }
                else
                {
                    outBytes.AddRange(c.DoFinal(data, offset, inputLength - offset));
                }
                i++;
                offset = i * maxBlock;
            }
            return Convert.ToBase64String(outBytes.ToArray());
        }

        private static byte[] Decrypt(byte[] input, string privateKeyPath)
        {
            PemReader r = new PemReader(new StreamReader(privateKeyPath));     //载入私钥
            var readObject = r.ReadObject();

            RsaPrivateCrtKeyParameters priKey = (RsaPrivateCrtKeyParameters)readObject;
            string mode = "RSA";
            IBufferedCipher c = CipherUtilities.GetCipher(mode);
            c.Init(false, priKey);

            byte[] outBytes = c.DoFinal(input);
            return outBytes;
        }

        private static byte[] Decrypt(byte[] input, RsaPrivateCrtKeyParameters priKey)
        {
            string mode = "RSA/ECB/PKCS1Padding";
            IBufferedCipher c = CipherUtilities.GetCipher(mode);
            c.Init(false, priKey);

            byte[] outBytes = c.DoFinal(input);
            return outBytes;
        }

        public static string RSADecryptByPrivateKey(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return string.Empty;
            }
            var bs = Convert.FromBase64String(text);
            var rst = new List<byte>();

            #region 分段解密 解决加密密文过长问题
            int len = 256;
            int m = bs.Length / len;
            if (m * len != bs.Length)
            {
                m = m + 1;
            }

            PemReader r = new PemReader(new StreamReader(privateKeyFile));     //载入私钥
            var readObject = r.ReadObject();

            RsaPrivateCrtKeyParameters priKey = (RsaPrivateCrtKeyParameters)readObject;

            for (int i = 0; i < m; i++)
            {
                byte[] temp = new byte[256];

                if (i < m - 1)
                {
                    temp = bs.Skip(i * len).Take(len).ToArray();
                }
                else
                {
                    temp = new byte[bs.Length % len == 0 ? 1 * len : bs.Length % len];
                    bs.Skip(i * len).Take(bs.Length % len == 0 ? len : bs.Length % len).ToArray().CopyTo(temp, 0);
                }
                rst.AddRange(Decrypt(temp, priKey));
            }
            #endregion

            //return BitConverter.ToString(rst.ToArray());
            return Encoding.UTF8.GetString(rst.ToArray());
        }
        #endregion

        public class PayUtils
        {
            private static readonly string hexChars = "0123456789ABCDEF";
            /// <summary>
            /// Bytes数组转为16进制
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public static string byteArray2HexString(byte[] data)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                {
                    byte lo = (byte)(0xF & data[i]);
                    byte hi = (byte)((int)((uint)(0xF0 & data[i]) >> 4));
                    sb.Append(hexChars.Substring(hi, 1)).Append(hexChars.Substring(lo, 1));
                }
                return sb.ToString();
            }
            /// <summary>
            /// 16进制转为Bytes数组
            /// </summary>
            /// <param name="hexStr"></param>
            /// <returns></returns>
            public static byte[] hexString2ByteArray(String hexStr)
            {
                if (hexStr.Length % 2 != 0)
                {
                    return null;
                }
                byte[] data = new byte[hexStr.Length / 2];
                for (int i = 0; i < hexStr.Length / 2; i++)
                {
                    char hc = hexStr.Substring(2 * i, 1).ToCharArray()[0];//.charAt(2 * i);
                    char lc = hexStr.Substring(2 * i + 1, 1).ToCharArray()[0];//.charAt(2 * i + 1);
                    byte hb = hexChar2Byte(hc);
                    byte lb = hexChar2Byte(lc);
                    if ((hb < 0) || (lb < 0))
                    {
                        return null;
                    }
                    int n = hb << 4;
                    data[i] = ((byte)(n + lb));
                }
                return data;
            }
            private static byte hexChar2Byte(char c)
            {
                if ((c >= '0') && (c <= '9'))
                {
                    return (byte)(c - '0');
                }
                if ((c >= 'a') && (c <= 'f'))
                {
                    return (byte)(c - 'a' + 10);
                }
                if ((c >= 'A') && (c <= 'F'))
                {
                    return (byte)(c - 'A' + 10);
                }
                return 0;
            }
        }
    }
}
